package com.manage.auth;

import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import org.springframework.security.access.ConfigAttribute;
import org.springframework.security.access.SecurityConfig;
import org.springframework.security.web.FilterInvocation;
import org.springframework.security.web.access.intercept.FilterInvocationSecurityMetadataSource;
import org.springframework.security.web.util.AntUrlPathMatcher;
import org.springframework.security.web.util.UrlMatcher;
import com.service.auth.IRoleResService;
/** 
 * 此类在初始化时，应该取到所有资源及其对应角色的定义
 * @author Robin
 */
public class MyInvocationSecurityMetadataSource
        implements FilterInvocationSecurityMetadataSource {
	
	private static final Logger log = Logger.getLogger(MyInvocationSecurityMetadataSource.class);
    private UrlMatcher urlMatcher = new AntUrlPathMatcher();;
    private static Map<String, Collection<ConfigAttribute>> resourceMap = null;
    private IRoleResService roleResService;

	public IRoleResService getRoleResService() {
		return roleResService;
	}

	public void setRoleResService(IRoleResService roleResService) {
		this.roleResService = roleResService;
	}

	public MyInvocationSecurityMetadataSource(IRoleResService roleResService) {
		this.roleResService = roleResService;
    }
	
	public static void cleanResource(){
		resourceMap = null;
	}
	
	/**
	 * 加载所有资源链接的也许访问的角色 
	 */
	@SuppressWarnings("unchecked")
	private void loadResourceDefine() {
    	try{
	        resourceMap = new HashMap<String, Collection<ConfigAttribute>>();
	        //此处要修改一下
	        List<Map> list = this.roleResService.getAllRolesUrls();
	        for(int i=0;i<list.size();i++){
	        	Map map = list.get(i);
	        	
	        	String roleId = "";
	        	
	        	if(map.get("ROLEID")!=null){
	        		roleId = map.get("ROLEID").toString();
	        	}
	        	String urls = map.get("URLS").toString();
	        	if(StringUtils.isNotBlank(roleId) && StringUtils.isNotBlank(urls) ){
	        		ConfigAttribute ca = new SecurityConfig(roleId);
	        		String[] urlAry = urls.split("@");
	        		for(int j=0;j<urlAry.length;j++){
	        			String url = urlAry[j];
	        			if(StringUtils.isNotBlank(url)){
		        			Collection<ConfigAttribute> conn = resourceMap.get(url);
		        			if(conn==null){
		        				conn = new HashSet<ConfigAttribute>();
		        				conn.add(ca);
		        				resourceMap.put(url, conn);
		        			}else{
		        				conn.add(ca);
		        				resourceMap.put(url, conn);
		        			}
	        			}
	        		}
	        	}
	        }
    	}catch(Exception e){
    		log.error("加载所有栏目出错",e);
    	}
    }

    // According to a URL, Find out permission configuration of this URL.
    public Collection<ConfigAttribute> getAttributes(Object object)
            throws IllegalArgumentException {
    	
    	if(resourceMap==null){
    		loadResourceDefine();
    	}
    	
        String url = ((FilterInvocation)object).getRequestUrl();
        if(!StringUtils.isEmpty(url) && url.indexOf("?")>-1){//去掉后面的参数
        	url = url.substring(0,url.indexOf("?"));
        }
        
        Collection<ConfigAttribute> coll = new HashSet<ConfigAttribute>();
        Iterator<String> ite = resourceMap.keySet().iterator();
        while (ite.hasNext()) {
            String resURL = ite.next();
            if (urlMatcher.pathMatchesUrl(url, resURL)) {
                if(resourceMap.get(resURL)!=null){
                	coll = resourceMap.get(resURL);
                	return coll;
                }
            }
        }
        return coll;
    }

    public boolean supports(Class<?> clazz) {
        return true;
    }
    
    public Collection<ConfigAttribute> getAllConfigAttributes() {
        return null;
    }
    
    /**
     * 判断当前用户是否拥有此URL权限
     * @param url url访问链接
     * @param roleCodeList 用户的角色列表
     * @return
     */
    public static boolean checkUrlAndRoleCode(String url, List<String> roleCodeList) {
        Collection<ConfigAttribute> collCa = resourceMap.get(url);
        if(collCa==null){
            return false;
        }
        if(roleCodeList == null && roleCodeList.size()<1){
        	return false;
        }
        for (ConfigAttribute ca : collCa) {
        	for(int i=0;i<roleCodeList.size();i++){
        		String roleCode = roleCodeList.get(i);
	            if (ca.getAttribute()!=null && ca.getAttribute().equals(roleCode)) {
	                return true;
	            }
        	}
        }
        return false;
    }

}
